﻿// 项目：	Cms.Data - Cms
// 文件名：	RepositoryBase.cs
// 
// 修改时间：2013-03-02 18:41
// 修改人：	Cooclsee

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Guan.CMS.Data.Infrastructure
{
    public abstract class RepositoryBase<T> where T : class
    {
        private CmsDataContext _dataContext;
        private readonly IDbSet<T> _dbset;

        protected RepositoryBase(IDatabaseFactory databaseFactory)
        {
            this.DatabaseFactory = databaseFactory;
            this._dbset = this.DataContext.Set<T>();
        }

        protected IDatabaseFactory DatabaseFactory { get; private set; }

        protected CmsDataContext DataContext
        {
            get { return this._dataContext ?? (this._dataContext = this.DatabaseFactory.Get()); }
        }

        public virtual void Add(T entity)
        {
            this._dbset.Add(entity);
        }

        public virtual void Update(T entity)
        {
            this._dbset.Attach(entity);
            this._dataContext.Entry(entity).State = EntityState.Modified;
        }

        public virtual void AddOrUpdate(T entity)
        {
            bool isUpdate = false;
            //找到主键
            var keys =
                entity.GetType().GetProperties().Where(c => c.GetCustomAttributes(typeof(KeyAttribute), true).Any());
            foreach (PropertyInfo key in keys)
            {
                //主键类型
                var keyType = key.PropertyType;
                var val = key.GetValue(entity, null);
                if (keyType == typeof(string))
                {
                    if (val as string != default(string))
                    {
                        isUpdate = true;
                        break;
                    }
                }
                else if (keyType == typeof(int))
                {
                    if (Convert.ToInt32(val) != default(int))
                    {
                        isUpdate = true;
                        break;
                    }
                }
            }
            if (isUpdate)
            {
                // Existing entity
                this.Update(entity);
            }
            else
            {
                // New entity
                this.Add(entity);
            }
        }

        public virtual void Delete(T entity)
        {
            this._dbset.Remove(entity);
        }

        public virtual void Delete(Expression<Func<T, bool>> where)
        {
            IEnumerable<T> objects = this._dbset.Where<T>(where).AsEnumerable();
            foreach (T obj in objects)
            {
                this._dbset.Remove(obj);
            }
        }

        public virtual T GetById(long id)
        {
            return this._dbset.Find(id);
        }

        public virtual T GetById(string id)
        {
            return this._dbset.Find(id);
        }

        public virtual IEnumerable<T> GetAll()
        {
            return this._dbset.ToList();
        }

        public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
        {
            return this._dbset.Where(where).ToList();
        }

        public virtual IQueryable<T> GetList()
        {
            return this._dbset;
        }

        public virtual IQueryable<T> GetList(Expression<Func<T, bool>> where)
        {
            return this._dbset.Where(where);
        }

        public T Get(Expression<Func<T, bool>> where)
        {
            return this._dbset.Where(where).FirstOrDefault<T>();
        }
    }
}